﻿using System.ComponentModel.DataAnnotations.Schema;

namespace Devonline.Core;

/// <summary>
/// 默认的基础配置
/// </summary>
public class AppSetting
{
    public AppSetting()
    {
        CachePrefix = "dev_";
        CacheExpireTime = AppSettings.UNIT_HOURS_A_DAY;
    }

    /// <summary>
    /// 启动站点配置
    /// </summary>
    public string? Hosts { get; set; }
    /// <summary>
    /// aspnetcore 启动站点配置
    /// </summary>
    public string? Urls { get; set; }
    /// <summary>
    /// 允许访问的地址
    /// </summary>
    public string? AllowedHosts { get; set; }
    /// <summary>
    /// 跨域配置
    /// </summary>
    public string? CorsOrigins { get; set; }
    /// <summary>
    /// 默认密码
    /// </summary>
    public string? DefaultPassword { get; set; }
    /// <summary>
    /// 是否使用 Http 协议重定向
    /// </summary>
    public bool HttpFordwarded { get; set; }
    /// <summary>
    /// 使用 identity 数据库来启用用户身份认证功能
    /// </summary>
    public bool EnableIdentity { get; set; }
    /// <summary>
    /// 是否启用缓存, 全局缓存
    /// </summary>
    public bool EnableCache { get; set; }
    /// <summary>
    /// 默认应用数据库连接字符串
    /// </summary>
    public string? ApplicationDbContext { get; set; }
    /// <summary>
    /// 默认身份数据库连接字符串
    /// </summary>
    public string? IdentityDbContext { get; set; }
    /// <summary>
    /// 默认缓存数据库连接字符串
    /// </summary>
    public string? CacheConfiguration { get; set; }
    /// <summary>
    /// 消息中心在 redis 中记录的消息前缀
    /// </summary>
    public string? CachePrefix { get; set; }
    /// <summary>
    /// 缓存过期时间, 单位: 小时, 默认一天
    /// </summary>
    public int CacheExpireTime { get; set; }
    /// <summary>
    /// 系统使用的时间类型, 默认: 本地时间
    /// </summary>
    public DateTimeKind DateTimeKind { get; set; } = DateTimeKind.Local;
    /// <summary>
    /// 发布协议, 此处仅支持 Http 和 Https, 默认 Http
    /// </summary>
    public ProtocolType ProtocolType { get; set; }
    /// <summary>
    /// 数据库类型
    /// </summary>
    public DatabaseType DatabaseType { get; set; }
    /// <summary>
    /// 数据保护级别
    /// </summary>
    public DataProtectionLevel ProtectionLevel { get; set; }

    /// <summary>
    /// 任务执行相关配置选型
    /// </summary>
    public ExecuteSetting? Execute { get; set; }
    /// <summary>
    /// 附件相关配置项
    /// </summary>
    public AttachmentSetting? Attachment { get; set; }
    /// <summary>
    /// identity options
    /// </summary>
    public IdentitySetting? Identity { get; set; }
    /// <summary>
    /// user interaction setting
    /// </summary>
    public UserInteractionSetting? UserInteraction { get; set; }
    /// <summary>
    /// https certificate configuration
    /// </summary>
    public CertificateSetting? Certificate { get; set; }
}

/// <summary>
/// 任务执行相关配置选项
/// </summary>
public class ExecuteSetting
{
    /// <summary>
    /// 启用当前操作功能
    /// </summary>
    public bool Enable { get; set; }
    /// <summary>
    /// 执行间隔, 单位秒
    /// </summary>
    public int ExecuteInterval { get; set; } = AppSettings.UNIT_SECONDS_A_MINUTE;
    /// <summary>
    /// 查询间隔, 单位毫秒
    /// </summary>
    public int QueryInterval { get; set; } = AppSettings.UNIT_HUNDRED;
    /// <summary>
    /// 读数据的最大间隔时间, 即单次读取数据在最长等待多长时间后就要进行下一次读取, 单位: 秒
    /// </summary>
    public int ReadInterval { get; set; } = AppSettings.UNIT_SECONDS_A_MINUTE;
    /// <summary>
    /// 写数据的最大等待时间, 即单次写入数据时最长等待多长时间就要写入一次数据库, 无论是否有足够的数据, 单位: 秒
    /// </summary>
    public int WriteInterval { get; set; } = AppSettings.UNIT_SECONDS_A_MINUTE;
    /// <summary>
    /// 最大尝试次数, 操作失败时, 最大尝试次数
    /// </summary>
    public int MaxRetryCount { get; set; } = 3;
    /// <summary>
    /// 读数据的最大条数, 即单次读取数据的最大上限, 以限制每次读取的数据量
    /// </summary>
    public int MaxReadCount { get; set; } = 100;
    /// <summary>
    /// 写数据的最大条数, 即单次写入数据库的最大上限, 以限制每次写入的数据量
    /// </summary>
    public int MaxWriteCount { get; set; } = 100;
}

/// <summary>
/// 认证相关配置选项
/// </summary>
public class IdentitySetting
{
    /// <summary>
    /// 认证服务地址
    /// </summary>
    public string Authority { get; set; } = "https://localhost:9527";
    /// <summary>
    /// api 资源名称
    /// </summary>
    [Column("api_name")]
    public string? ApiName { get; set; }
    /// <summary>
    /// api 资源密钥
    /// </summary>
    [Column("api_secret")]
    public string? ApiSecret { get; set; }
    /// <summary>
    /// 客户端编号
    /// </summary>
    [Column("Client_Id")]
    public string? ClientId { get; set; }
    /// <summary>
    /// 客户端密钥
    /// </summary>
    [Column("client_secret")]
    public string? ClientSecret { get; set; }
    /// <summary>
    /// 授权类型
    /// </summary>
    [Column("grant_type")]
    public string? GrantType { get; set; } = "password";
    /// <summary>
    /// 返回值类型
    /// </summary>
    [Column("response_type")]
    public string? ResponseType { get; set; } = "token";
    /// <summary>
    /// 允许访问的 api 资源范围
    /// </summary>
    public string? Scope { get; set; }
    /// <summary>
    /// 获取 token 的地址
    /// </summary>
    public string Token { get; set; } = "/connect/token";
    /// <summary>
    /// 获取用户信息的地址
    /// </summary>
    public string UserInfo { get; set; } = "/connect/userinfo";
    /// <summary>
    /// Defines whether access and refresh tokens should be stored in the Microsoft.AspNetCore.Authentication.AuthenticationProperties
    ///     after a successful authorization. This property is set to false by default to
    ///     reduce the size of the final authentication cookie.
    /// </summary>
    public bool SaveTokens { get; set; } = true;
}

/// <summary>
/// 用户交互设置
/// </summary>
public class UserInteractionSetting
{
    /// <summary>
    /// Cookie Name
    /// </summary>
    public string CookieName { get; set; } = "Devonline.Identity.Cookies";
    /// <summary>
    /// 登录地址
    /// </summary>
    public string Login { get; set; } = "/Account/Login";
    /// <summary>
    /// 注销地址
    /// </summary>
    public string Logout { get; set; } = "/api/Account/Logout";
    /// <summary>
    /// 用户信息获取地址
    /// </summary>
    public string UserInfo { get; set; } = "/api/Account/GetUserInfo";
    /// <summary>
    /// 用户权限校验地址
    /// </summary>
    public string UserPermission { get; set; } = "/api/Account/UserHasPermission";
    /// <summary>
    /// 拒绝访问地址
    /// </summary>
    public string AccessDenied { get; set; } = "/Account/AccessDenied";
    /// <summary>
    /// 错误页面地址
    /// </summary>
    public string Error { get; set; } = "/Home/Error";
}
/// <summary>
/// https certificate configuration
/// </summary>
public class CertificateSetting
{
    /// <summary>
    /// 域名
    /// </summary>
    public string? Domain { get; set; }
    /// <summary>
    /// 证书地址
    /// </summary>
    public string? Path { get; set; }
    /// <summary>
    /// 证书密码
    /// </summary>
    public string? Password { get; set; }
}

/// <summary>
/// 附件相关选项
/// </summary>
public class AttachmentSetting
{
    /// <summary>
    /// 构造方法
    /// </summary>
    public AttachmentSetting()
    {
        EnableUpload = true;
        EnableImageThumbnail = true;
        RootPath = AppSettings.DEFAULT_ATTACHMENT_PATH;
        AllowFileExtensions = AppSettings.DEFAULT_ALLOW_FILE_EXTENSIONS;
        TempFileExtension = AppSettings.DEFAULT_TEMPORARY_FILE_EXTENSION;
        MaxUploadFileSize = AppSettings.DEFAULT_MAX_UPLOAD_FILE_SIZE;
        TotalUploadFileSize = AppSettings.DEFAULT_TOTAL_UPLOAD_FILE_SIZE;
        ImageThumbnailPrefix = AppSettings.DEFAULT_IMAGE_THUMBNAIL_PREFIX;
        ImageThumbnailSize = AppSettings.DEFAULT_IMAGE_THUMBNAIL_SIZE;
    }

    public bool EnableUpload { get; set; }
    /// <summary>
    /// 附件根路径
    /// </summary>
    public string RootPath { get; set; }
    /// <summary>
    /// 允许上传的附件类型
    /// </summary>
    public string AllowFileExtensions { get; set; }
    /// <summary>
    /// 临时文件扩展名
    /// </summary>
    public string TempFileExtension { get; set; }
    /// <summary>
    /// 单附件文件大小
    /// </summary>
    public int MaxUploadFileSize { get; set; }
    /// <summary>
    /// 总附件文件大小
    /// </summary>
    public int TotalUploadFileSize { get; set; }
    /// <summary>
    /// 启用图片文件自动创建缩略图
    /// </summary>
    public bool EnableImageThumbnail { get; set; }
    /// <summary>
    /// 图片文件缩略图前缀
    /// </summary>
    public string ImageThumbnailPrefix { get; set; }
    /// <summary>
    /// 图片文件缩略图尺寸
    /// </summary>
    public int ImageThumbnailSize { get; set; }
}